                            SOFTICE DETECTION
                            -----------------

Let's say you've never heard of "meltice" and that you're trying to find a way to detect SoftICE.

How can you do that ?

It's simple : when you run symbol loader (loader32.exe), you'll notice a "SoftICE is active" string or a "SoftICE is not active" string at the bottom right of the symbol loader.

That means symbol loader *knows* if SoftICE is active : let's disassemble loader32.exe and see what we can find (I'm using SoftICE 4.00 so the offsets may change if you use a different version).



--------------------------------------------------------------------------------
:0044660B 8B8310030000            mov eax, dword ptr [ebx+00000310]
:00446611 F7D8                    neg eax
:00446613 1BD2                    sbb edx, edx
:00446615 F7DA                    neg edx
:00446617 8B83E4010000            mov eax, dword ptr [ebx+000001E4]
:0044661D E80AEBFDFF              call 0042512C
:00446622 83BB0403000000          cmp dword ptr [ebx+00000304], 00000000
:00446629 7422                    je 0044664D
:0044662B 8B8300020000            mov eax, dword ptr [ebx+00000200]
:00446631 8B8018010000            mov eax, dword ptr [eax+00000118]
:00446637 BA01000000              mov edx, 00000001
:0044663C E89358FFFF              call 0043BED4

* Possible StringData Ref from Code Obj ->"SoftICE is active"
                                  |
:00446641 BA54674400              mov edx, 00446754
:00446646 E81558FFFF              call 0043BE60
:0044664B EB2C                    jmp 00446679

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00446629(C)
|
:0044664D 8B8300020000            mov eax, dword ptr [ebx+00000200]
:00446653 8B8018010000            mov eax, dword ptr [eax+00000118]
:00446659 BA01000000              mov edx, 00000001
:0044665E E87158FFFF              call 0043BED4

* Possible StringData Ref from Code Obj ->"SoftICE is not active"
                                  |
:00446663 BA70674400              mov edx, 00446770
:00446668 E8F357FFFF              call 0043BE60
--------------------------------------------------------------------------------



We see at @00446622 that if [ebx+00000304]=0 then SoftICE is not active.

Now let's run symbol loader and let's debug loader32.exe (in other words, we use symbol loader to debug himself ;)

When SoftICE pops at entrypoint, type 'BPX 446622' and let it run (F5).

It will pop again at @446622 :
:00446622 83BB0403000000          cmp dword ptr [ebx+00000304], 00000000

We want to know when something is written at [EBX+304] so, type 'BPM EBX+304' and F5

Nothing happens, so close symbol loader (the debugged one of course) and debug it again : now SoftICE will pop a few times and it'll finally pop at @43FFF4 :



--------------------------------------------------------------------------------
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0043FF5A(C), :0043FFDC(C)
|
:0043FFE5 8B430C                  mov eax, dword ptr [ebx+0C]
:0043FFE8 F7D8                    neg eax
:0043FFEA 1BC0                    sbb eax, eax
:0043FFEC F7D8                    neg eax
:0043FFEE 84C0                    test al, al
:0043FFF0 740A                    je 0043FFFC
:0043FFF2 8B03                    mov eax, dword ptr [ebx]
:0043FFF4 894304                  mov dword ptr [ebx+04], eax *** SoftICE pops here ***
:0043FFF7 8B03                    mov eax, dword ptr [ebx]
:0043FFF9 894308                  mov dword ptr [ebx+08], eax
--------------------------------------------------------------------------------



just one line above we see :
:0043FFF2 8B03                    mov eax, dword ptr [ebx]

so we 'BPM EBX' and we repeat the same stuff (close symbol loader and debug it again)



--------------------------------------------------------------------------------
:0043FF31 8BC3                    mov eax, ebx
:0043FF33 33C9                    xor ecx, ecx
:0043FF35 BA47000000              mov edx, 00000047
:0043FF3A E8E52AFCFF              call 00402A24
:0043FF3F E8D8FCFFFF              call 0043FC1C	
:0043FF44 8903                    mov dword ptr [ebx], eax *** Softice pops here ***
:0043FF46 C7430CFFFFFFFF          mov [ebx+0C], FFFFFFFF
:0043FF4D 83CFFF                  or edi, FFFFFFFF
:0043FF50 8B03                    mov eax, dword ptr [ebx]
--------------------------------------------------------------------------------



hmm... that 'CALL 43FC1C' looks interesting :



--------------------------------------------------------------------------------
* Reference To: NMTRANS.NmSymIsSoftICELoaded, Ord:0000h
        	                          |
	:0043FC1C E897FFFFFF              Call 0043FBB8
	:0043FC21 C3                      ret
--------------------------------------------------------------------------------


So Symbol loader uses the imported function NmSymIsSoftICELoaded from NMTRANS.DLL to know is SoftICE is loaded.
Yeah, I know, we could have found this imported functions quicker by having a look at the imported functions used by loader32.exe :



--------------------------------------------------------------------------------
Import Module 012: NMTRANS.DLL

 Addr:0004BF0C hint(0000) Name: NmSymLoadExecutable
 Addr:0004BF22 hint(0000) Name: NmSymCreateLogFile
 Addr:0004BF38 hint(0000) Name: NmSymIsSoftICELoaded <-- HERE !
 Addr:0004BF50 hint(0000) Name: NmSymGetModuleLoadRecord
 Addr:0004BF6C hint(0000) Name: NmSymLoadExports
 Addr:0004BF80 hint(0000) Name: NmSymNm32RemoveSymbolTable
 Addr:0004BF9E hint(0000) Name: NmSymNm32QueryTableInfoNext
 Addr:0004BFBC hint(0000) Name: NmSymNm32QueryTableInfoFirst
 Addr:0004BFDC hint(0000) Name: NmSymNm32QueryTables
 Addr:0004BFF4 hint(0000) Name: NmSymGetSoftICEVersionInfo
 Addr:0004C012 hint(0000) Name: NmSymLoadNm32SymbolTable
 Addr:0004C02E hint(0000) Name: NmSymGetErrorMessage
 Addr:0004C046 hint(0000) Name: NmSymGetTranslatorVersionInfo
 Addr:0004C066 hint(0000) Name: NmSymProcessDebugInfoForFile
--------------------------------------------------------------------------------


so know we disassemble NMTRANS.DLL and we look for NmSymIsSoftICELoaded :



--------------------------------------------------------------------------------
Exported fn(): NmSymIsSoftICELoaded - Ord:0015h
* Reference To: nmtrans.DevIO_ConnectToSoftICE
                                  |
:10017710 E8AB210000              call 100198C0
:10017715 83F8FF                  cmp eax, FFFFFFFF
:10017718 740D                    je 10017727 -> Jump if SoftICE is not loaded
:1001771A 50                      push eax

* Reference To: KERNEL32.CloseHandle, Ord:0017h
                                  |
:1001771B FF150C421C10            Call dword ptr [101C420C]
:10017721 B801000000              mov eax, 00000001
:10017726 C3                      ret


* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10017718(C)
|
:10017727 33C0                    xor eax, eax
:10017729 C3                      ret
--------------------------------------------------------------------------------



Let's have a look at that nmtrans.DevIO_ConnectToSoftICE function (also known as meltice) :



--------------------------------------------------------------------------------
Exported fn(): DevIO_ConnectToSoftICE - Ord:0002h
:100198C0 56                      push esi
:100198C1 57                      push edi
:100198C2 6A00                    push 00000000
:100198C4 6880000000              push 00000080
:100198C9 6A03                    push 00000003

* Reference To: KERNEL32.CreateFileA, Ord:0030h
                                  |
:100198CB 8B3528421C10            mov esi, dword ptr [101C4228]
:100198D1 6A00                    push 00000000
:100198D3 6A03                    push 00000003
:100198D5 6800000080              push 80000000

* Possible StringData Ref from Data Obj ->"\\.\SICE"
                                  |
:100198DA 6824950710              push 10079524
:100198DF FFD6                    call esi
:100198E1 83F8FF                  cmp eax, FFFFFFFF
:100198E4 8BF8                    mov edi, eax
:100198E6 752B                    jne 10019913 -> Jump if SoftICE is loaded
:100198E8 6A00                    push 00000000 NULL
:100198EA 6880000000              push 00000080 FILE_ATTRIBUTE_NORMAL
:100198EF 6A03                    push 00000003 OPEN_EXISTING
:100198F1 6A00                    push 00000000 NULL
:100198F3 6A03                    push 00000003 FILE_SHARE_READ | FILE_SHARE_WRITE
:100198F5 6800000080              push 80000000 GENERIC_READ

* Possible StringData Ref from Data Obj ->"\\.\NTICE"
                                  |
:100198FA 6818950710              push 10079518
:100198FF FFD6                    call esi
:10019901 83F8FF                  cmp eax, FFFFFFFF
:10019904 8BF8                    mov edi, eax
:10019906 750B                    jne 10019913 -> Jump if SoftICE is loaded
:10019908 68010058A6              push A6580001

* Reference To: KERNEL32.SetLastError, Ord:0219h
                                  |
:1001990D FF15B4421C10            Call dword ptr [101C42B4]

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:100198E6(C), :10019906(C)
|
:10019913 8BC7                    mov eax, edi
:10019915 5F                      pop edi
:10019916 5E                      pop esi
:10019917 C3                      ret
--------------------------------------------------------------------------------


So here is the world famous "meltice" trick which enables you to know if SoftICE is loaded :


BOOL IsSoftIce95Loaded()
{
	HANDLE hFile;  
 
	hFile = CreateFile( "\\\\.\\SICE",	
						GENERIC_READ | GENERIC_WRITE,
						FILE_SHARE_READ | FILE_SHARE_WRITE,
						NULL,
						OPEN_EXISTING,
						FILE_ATTRIBUTE_NORMAL,
						NULL);

	if( hFile != INVALID_HANDLE_VALUE )
	{
		CloseHandle(hFile);
		return TRUE; // SoftICE loaded
	}

	return FALSE; // SoftICE not loaded
}




additional comments :
---------------------

Createfile is used to open the vxd driver called SICE : this is done by using the string \\.\SICE as argument. The only doc I've found related to this method is in a VC++ header file : "you can dyna-load VxDs with CreateFile(\\.\vxd_regstr_keyname)"

Some progs don't use "createfile" but "_lopen" which does exactly the same thing... but it's only to confuse crackers ;) (thx to Alpine for showing me this trick)

Symbol loader was coded using Delphi... which surprised me ;)

I knew the "SoftICE is active" string was in loader32.exe because I used a stringdumper before disassembling it.





thx to : 
--------

+Frog's print (READ frogsice documentation for softice detection)
Alpine (_lopen)
David Eriksson (meltice trick)

    ________     _______     _______
   /__   __/\   /  ____/\   /  ____/\
   \_/  /\_\/  /  /\___\/  /  /\___\/
    /  / /    /  /_/_     /  / / 
   /  / /    /____  /\   /  / /
  /  / /     \___/ / /  /  / /
 /  / /     ____/ / /  /  /_/_
/  / /     /_____/ /  /______/\
\__\/      \_____\/   \______\/ 18/01/2000